@vezham/icons-react-native 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +19 -0
- package/LICENSE +32 -0
- package/README.md +176 -0
- package/package.json +23 -0
- package/scripts/build.cjs +463 -0
- package/src/createIcon.d.ts +26 -0
- package/src/createIcon.js +63 -0
- package/src/icons/.gitkeep +1 -0
- package/tsconfig.json +20 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# @vezham/icons-react-native
|
|
2
|
+
|
|
3
|
+
## 1.0.0
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`4bc7ae2`](https://github.com/vezham/reicon/commit/4bc7ae21342fe26c90359bc0d5cbb74258b32fe7) Thanks [@vx-vigneshwaran](https://github.com/vx-vigneshwaran)! - ver bump
|
|
8
|
+
|
|
9
|
+
## 1.0.1
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- [`345a93a`](https://github.com/vezham/reicon/commit/345a93aa6f5a5b7f0d4598a0708eb24dd704046a) Thanks [@vx-vigneshwaran](https://github.com/vx-vigneshwaran)! - ver bump
|
|
14
|
+
|
|
15
|
+
## 1.0.0
|
|
16
|
+
|
|
17
|
+
### Patch Changes
|
|
18
|
+
|
|
19
|
+
- [`ccfadd2`](https://github.com/vezham/reicon/commit/ccfadd29b3031f81cc6986d9e2ff084eca798c81) Thanks [@vx-vigneshwaran](https://github.com/vx-vigneshwaran)! - init test
|
package/LICENSE
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
SPDX-License-Identifier: MIT
|
|
2
|
+
|
|
3
|
+
Attribution:
|
|
4
|
+
Creator / Maintainer : Vezham Technologies Private Limited
|
|
5
|
+
Original Author : REICON
|
|
6
|
+
Licensor : Vezham Technologies Private Limited
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2025 REICON.
|
|
9
|
+
Copyright (c) 2025–present Vezham Technologies Private Limited. All rights reserved.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
MIT License
|
|
14
|
+
|
|
15
|
+
Copyright (c) 2025 REICON
|
|
16
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
17
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
18
|
+
in the Software without restriction, including without limitation the rights
|
|
19
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
20
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
21
|
+
furnished to do so, subject to the following conditions:
|
|
22
|
+
|
|
23
|
+
The above copyright notice and this permission notice shall be included in all
|
|
24
|
+
copies or substantial portions of the Software.
|
|
25
|
+
|
|
26
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
27
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
28
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
29
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
30
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
31
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
32
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<a href="https://npmjs.com/package/reicon-react-native"><img src="https://img.shields.io/npm/v/reicon-react-native?color=black&label=npm" alt="npm version" /></a>
|
|
3
|
+
<a href="https://npmjs.com/package/reicon-react-native"><img src="https://img.shields.io/npm/dm/reicon-react-native?color=black&label=downloads" alt="npm downloads" /></a>
|
|
4
|
+
<a href="https://github.com/dqev/reicon/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MIT-black" alt="MIT License" /></a>
|
|
5
|
+
<a href="https://reicon.dev"><img src="https://img.shields.io/badge/docs-reicon.dev-black" alt="Documentation" /></a>
|
|
6
|
+
</p>
|
|
7
|
+
|
|
8
|
+
# Reicon React Native
|
|
9
|
+
|
|
10
|
+
> 2674+ pixel-perfect SVG icons • Outline & Filled weights • React Native component wrapper • Zero dependencies • MIT Licensed
|
|
11
|
+
|
|
12
|
+
**Reicon React Native** is the official React Native package for Reicon — a free, open-source SVG icon library with 2674+ handcrafted, grid-aligned icons built for developers and designers. Every component is optimized for tree-shaking and fully TypeScript-ready.
|
|
13
|
+
|
|
14
|
+
- 🔗 **Website & icon browser:** [reicon.dev](https://reicon.dev)
|
|
15
|
+
- 📦 **Core package:** [reicon](https://npmjs.com/package/reicon)
|
|
16
|
+
- ⚛️ **React package:** [reicon-react](https://npmjs.com/package/reicon-react)
|
|
17
|
+
- 🎨 **Figma plugin:** [reicon.dev/figma](https://reicon.dev/figma)
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Install
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npm i reicon-react-native react-native-svg
|
|
25
|
+
# or
|
|
26
|
+
yarn add reicon-react-native react-native-svg
|
|
27
|
+
# or
|
|
28
|
+
bun add reicon-react-native react-native-svg
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
**Note:** This package requires `react-native-svg` as a peer dependency. Make sure to install it and follow its [setup instructions](https://github.com/software-mansion/react-native-svg#installation).
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Usage
|
|
36
|
+
|
|
37
|
+
```jsx
|
|
38
|
+
import { Home, ShieldCheck, AltArrowDown } from 'reicon-react-native';
|
|
39
|
+
|
|
40
|
+
function App() {
|
|
41
|
+
return (
|
|
42
|
+
<View>
|
|
43
|
+
<Home />
|
|
44
|
+
<ShieldCheck size={32} color="#d97757" />
|
|
45
|
+
<AltArrowDown weight="Filled" />
|
|
46
|
+
</View>
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Props
|
|
52
|
+
|
|
53
|
+
| Prop | Type | Default | Description |
|
|
54
|
+
|------|------|---------|-------------|
|
|
55
|
+
| `size` | `number` | `24` | Icon size in pixels |
|
|
56
|
+
| `color` | `string` | `#000000` | Primary icon color |
|
|
57
|
+
| `secondaryColor` | `string` | same as color | Secondary color |
|
|
58
|
+
| `weight` | `IconWeight` | `Outline` | Icon weight / style |
|
|
59
|
+
| `strokeWidth` | `number | string` | — | Override stroke width |
|
|
60
|
+
|
|
61
|
+
Plus all standard `react-native-svg` SVG props.
|
|
62
|
+
|
|
63
|
+
### Weights
|
|
64
|
+
|
|
65
|
+
- **Outline** — clean outlined style (default)
|
|
66
|
+
- **Filled** — solid filled style
|
|
67
|
+
|
|
68
|
+
```jsx
|
|
69
|
+
import { Home } from 'reicon-react-native';
|
|
70
|
+
|
|
71
|
+
<Home /> {/* Outline (default) */}
|
|
72
|
+
<Home weight="Filled" /> {/* Filled */}
|
|
73
|
+
<Home weight="Filled" color="red" />
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Direct icon import (smallest bundle)
|
|
77
|
+
|
|
78
|
+
```jsx
|
|
79
|
+
import Home from 'reicon-react-native/icons/Home';
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### All react-native-svg props are supported
|
|
83
|
+
|
|
84
|
+
```jsx
|
|
85
|
+
<Home
|
|
86
|
+
size={48}
|
|
87
|
+
color="red"
|
|
88
|
+
style={{ marginRight: 8 }}
|
|
89
|
+
onPress={() => console.log('pressed')}
|
|
90
|
+
/>
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## Tree-shaking — import only what you use
|
|
96
|
+
|
|
97
|
+
Every icon is a standalone ES module. Metro bundler will tree-shake unused icons automatically.
|
|
98
|
+
|
|
99
|
+
```jsx
|
|
100
|
+
// ✅ Only Home is included in your bundle
|
|
101
|
+
import { Home } from 'reicon-react-native';
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## Icon Names
|
|
107
|
+
|
|
108
|
+
Icons use **PascalCase**, derived from their original kebab-case names:
|
|
109
|
+
|
|
110
|
+
| Original name | Import |
|
|
111
|
+
|---------------|--------|
|
|
112
|
+
| `home` | `Home` |
|
|
113
|
+
| `shield-check` | `ShieldCheck` |
|
|
114
|
+
| `alt-arrow-down` | `AltArrowDown` |
|
|
115
|
+
| `shopping-cart` | `ShoppingCart` |
|
|
116
|
+
| `user-circle` | `UserCircle` |
|
|
117
|
+
|
|
118
|
+
Browse all 2674+ icons at [reicon.dev](https://reicon.dev).
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## TypeScript
|
|
123
|
+
|
|
124
|
+
Full TypeScript support out of the box:
|
|
125
|
+
|
|
126
|
+
```tsx
|
|
127
|
+
import { Home, IconProps, IconWeight } from 'reicon-react-native';
|
|
128
|
+
|
|
129
|
+
const weight: IconWeight = 'Filled';
|
|
130
|
+
const props: IconProps = { size: 32, color: '#d97757', weight };
|
|
131
|
+
|
|
132
|
+
<Home {...props} />
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## Why Reicon?
|
|
138
|
+
|
|
139
|
+
| | Reicon | React Native Vector Icons | Lucide RN |
|
|
140
|
+
|--|--------|---------------------------|-----------|
|
|
141
|
+
| **Icons** | 2674+ | 3000+ | 1600+ |
|
|
142
|
+
| **Weights** | Outline + Filled | Varies by set | Outline only |
|
|
143
|
+
| **Tree-shakeable** | ✅ | ❌ | ✅ |
|
|
144
|
+
| **TypeScript** | ✅ | ✅ | ✅ |
|
|
145
|
+
| **Zero dependencies** | ✅ (+ react-native-svg) | ✅ | ✅ (+ react-native-svg) |
|
|
146
|
+
| **MIT License** | ✅ | ✅ | ✅ |
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
## Related packages
|
|
151
|
+
|
|
152
|
+
| Package | Description |
|
|
153
|
+
|---------|-------------|
|
|
154
|
+
| [`reicon`](https://npmjs.com/package/reicon) | Core vanilla JS + CDN |
|
|
155
|
+
| [`reicon-react`](https://npmjs.com/package/reicon-react) | React components for all 2674+ icons |
|
|
156
|
+
| [`reicon-react-native`](https://npmjs.com/package/reicon-react-native) | **This package.** React Native components for all 2674+ icons |
|
|
157
|
+
| [`reicon-vue`](https://npmjs.com/package/reicon-vue) | Vue 3 components for all 2674+ icons |
|
|
158
|
+
| [`reicon-svelte`](https://npmjs.com/package/reicon-svelte) | Svelte components for all 2674+ icons |
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## Links
|
|
163
|
+
|
|
164
|
+
- 🌐 Website: [reicon.dev](https://reicon.dev)
|
|
165
|
+
- 📖 Documentation: [reicon.dev/docs](https://reicon.dev/docs)
|
|
166
|
+
- 📦 npm (React Native): [npmjs.com/package/reicon-react-native](https://npmjs.com/package/reicon-react-native)
|
|
167
|
+
- 🐙 GitHub: [github.com/dqev/reicon](https://github.com/dqev/reicon)
|
|
168
|
+
- 🐛 Issues: [github.com/dqev/reicon/issues](https://github.com/dqev/reicon/issues)
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
## License
|
|
173
|
+
|
|
174
|
+
MIT © [Dev Chauhan](https://devchauhan.in)
|
|
175
|
+
|
|
176
|
+
Free to use in personal and commercial projects.
|
package/package.json
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@vezham/icons-react-native",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "React Native icon components for Reicon.",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "https://github.com/vezham/reicon",
|
|
9
|
+
"directory": "packages/icons-react-native"
|
|
10
|
+
},
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/vezham/reicon/issues"
|
|
13
|
+
},
|
|
14
|
+
"homepage": "https://vezham.com",
|
|
15
|
+
"peerDependencies": {
|
|
16
|
+
"react": ">=16.8.0",
|
|
17
|
+
"react-native": ">=0.64.0",
|
|
18
|
+
"react-native-svg": ">=12.0.0"
|
|
19
|
+
},
|
|
20
|
+
"scripts": {
|
|
21
|
+
"build": "node scripts/build.cjs"
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,463 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* build.cjs — Generates the `reicon-react-native` package from icondata.json
|
|
4
|
+
*
|
|
5
|
+
* Usage: node packages/icons-react-native/scripts/build.cjs (or: npm run build:react-native)
|
|
6
|
+
*
|
|
7
|
+
* Output:
|
|
8
|
+
* src/icons/ Individual React Native icon files and type declarations (git-ignored)
|
|
9
|
+
* src/index.js Barrel ESM exports (git-ignored)
|
|
10
|
+
* src/index.d.ts Barrel TypeScript declarations (git-ignored)
|
|
11
|
+
* dist/ Standard NPM package ready to publish (git-ignored)
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
const fs = require('fs');
|
|
15
|
+
const path = require('path');
|
|
16
|
+
|
|
17
|
+
// ── paths ──────────────────────────────────────────────────────────────────
|
|
18
|
+
const DATA_PATH = path.join(__dirname, '..', '..', '..', 'data', 'icon-data.json');
|
|
19
|
+
const TAGS_PATH = path.join(__dirname, '..', '..', '..', 'data', 'icon-tags.json');
|
|
20
|
+
const SRC = path.join(__dirname, '..', 'src');
|
|
21
|
+
const DIST = path.join(__dirname, '..', 'dist');
|
|
22
|
+
|
|
23
|
+
// ── weight short keys ──────────────────────────────────────────────────────
|
|
24
|
+
const W_KEY = { Filled: 'F', Outline: 'O' };
|
|
25
|
+
|
|
26
|
+
// ── helpers ────────────────────────────────────────────────────────────────
|
|
27
|
+
function toPascalCase(str) {
|
|
28
|
+
return str
|
|
29
|
+
.split('-')
|
|
30
|
+
.map(s => s.charAt(0).toUpperCase() + s.slice(1))
|
|
31
|
+
.join('');
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function stripSvgWrapper(code) {
|
|
35
|
+
if (!code) return '';
|
|
36
|
+
return code.replace(/^<svg[^>]*>/, '').replace(/<\/svg>\s*$/, '').trim();
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Fix hardcoded fill="white" → currentColor so user color prop works correctly.
|
|
40
|
+
function rewriteColors(svg) {
|
|
41
|
+
return svg.replace(/fill="white"/g, 'fill="currentColor"');
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function escapeForJS(s) {
|
|
45
|
+
return s.replace(/\\/g, '\\\\').replace(/`/g, '\\`').replace(/\$\{/g, '\\${');
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Build a base64 data URI for an inline SVG preview (shown in IDE hover).
|
|
50
|
+
*/
|
|
51
|
+
function buildPreviewDataUri(weights) {
|
|
52
|
+
const inner = weights['O'] || weights['F'] || '';
|
|
53
|
+
if (!inner) return '';
|
|
54
|
+
const svg = `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none">${inner}</svg>`
|
|
55
|
+
.replace(/currentColor/g, '#e4e4e7')
|
|
56
|
+
.replace(/__RI_SECONDARY__/g, '#9ca3af');
|
|
57
|
+
return `data:image/svg+xml;base64,${Buffer.from(svg).toString('base64')}`;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// ── read data ──────────────────────────────────────────────────────────────
|
|
61
|
+
console.log('Reading icondata.json …');
|
|
62
|
+
const data = JSON.parse(fs.readFileSync(DATA_PATH, 'utf-8'));
|
|
63
|
+
|
|
64
|
+
let TAGS = {};
|
|
65
|
+
if (fs.existsSync(TAGS_PATH)) {
|
|
66
|
+
TAGS = JSON.parse(fs.readFileSync(TAGS_PATH, 'utf-8'));
|
|
67
|
+
console.log(`Read ${Object.keys(TAGS).length} tag entries`);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// ── collect icons ──────────────────────────────────────────────────────────
|
|
71
|
+
const icons = [];
|
|
72
|
+
const pascalLowerSet = new Set();
|
|
73
|
+
|
|
74
|
+
for (const [catKey, catData] of Object.entries(data.categories || {})) {
|
|
75
|
+
for (const [iconKey, icon] of Object.entries(catData.icons || {})) {
|
|
76
|
+
let pascal = toPascalCase(iconKey);
|
|
77
|
+
|
|
78
|
+
if (pascalLowerSet.has(pascal.toLowerCase())) {
|
|
79
|
+
pascal += toPascalCase(catKey);
|
|
80
|
+
}
|
|
81
|
+
pascalLowerSet.add(pascal.toLowerCase());
|
|
82
|
+
|
|
83
|
+
const weights = {};
|
|
84
|
+
for (const [wName, wData] of Object.entries(icon.weights || {})) {
|
|
85
|
+
const short = W_KEY[wName];
|
|
86
|
+
if (short && wData.code) {
|
|
87
|
+
weights[short] = rewriteColors(stripSvgWrapper(wData.code));
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (Object.keys(weights).length > 0) {
|
|
92
|
+
icons.push({
|
|
93
|
+
kebab: iconKey,
|
|
94
|
+
pascal,
|
|
95
|
+
category: catKey,
|
|
96
|
+
weights,
|
|
97
|
+
tags: TAGS[iconKey] || icon.description || [],
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
icons.sort((a, b) => a.pascal.localeCompare(b.pascal));
|
|
104
|
+
console.log(`Found ${icons.length} icons`);
|
|
105
|
+
|
|
106
|
+
// ── clean & prepare src/icons ──────────────────────────────────────────────
|
|
107
|
+
fs.rmSync(path.join(SRC, 'icons'), { recursive: true, force: true });
|
|
108
|
+
fs.mkdirSync(path.join(SRC, 'icons'), { recursive: true });
|
|
109
|
+
|
|
110
|
+
// ── individual icon files ──────────────────────────────────────────────────
|
|
111
|
+
console.log('Generating React Native component files in src/icons/ …');
|
|
112
|
+
|
|
113
|
+
const barrelExports = [];
|
|
114
|
+
const dtsExports = [];
|
|
115
|
+
|
|
116
|
+
for (const icon of icons) {
|
|
117
|
+
const wEntries = Object.entries(icon.weights)
|
|
118
|
+
.map(([k, v]) => ` ${k}: \`${escapeForJS(v)}\``)
|
|
119
|
+
.join(',\n');
|
|
120
|
+
|
|
121
|
+
const previewUri = buildPreviewDataUri(icon.weights);
|
|
122
|
+
const kebab = icon.kebab;
|
|
123
|
+
|
|
124
|
+
// ── icon .js file with JSDoc ──
|
|
125
|
+
const iconJS = `import createIcon from '../createIcon.js';
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* @component
|
|
129
|
+
* @name ${icon.pascal}
|
|
130
|
+
* @description Reicon React Native SVG icon component
|
|
131
|
+
* @preview  - https://reicon.dev/icons/${kebab}
|
|
132
|
+
* @see https://reicon.dev/docs — Documentation
|
|
133
|
+
* @param {import('../createIcon').IconProps} props — Reicon icon props and any valid react-native-svg props
|
|
134
|
+
* @returns {JSX.Element} JSX Element
|
|
135
|
+
*/
|
|
136
|
+
const ${icon.pascal} = createIcon('${icon.pascal}', {
|
|
137
|
+
${wEntries}
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
export { ${icon.pascal} };
|
|
141
|
+
export default ${icon.pascal};
|
|
142
|
+
`;
|
|
143
|
+
|
|
144
|
+
fs.writeFileSync(path.join(SRC, 'icons', `${icon.pascal}.js`), iconJS);
|
|
145
|
+
|
|
146
|
+
// ── icon .d.ts file with JSDoc ──
|
|
147
|
+
const iconDTS = `import { IconComponent } from '../createIcon';
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* @component
|
|
151
|
+
* @name ${icon.pascal}
|
|
152
|
+
* @description Reicon React Native SVG icon component
|
|
153
|
+
* @preview  - https://reicon.dev/icons/${kebab}
|
|
154
|
+
* @see https://reicon.dev/docs — Documentation
|
|
155
|
+
* @param {import('../createIcon').IconProps} props — Reicon icon props and any valid react-native-svg props
|
|
156
|
+
* @returns {JSX.Element} JSX Element
|
|
157
|
+
*/
|
|
158
|
+
declare const ${icon.pascal}: IconComponent;
|
|
159
|
+
export { ${icon.pascal} };
|
|
160
|
+
export default ${icon.pascal};
|
|
161
|
+
`;
|
|
162
|
+
|
|
163
|
+
fs.writeFileSync(path.join(SRC, 'icons', `${icon.pascal}.d.ts`), iconDTS);
|
|
164
|
+
|
|
165
|
+
barrelExports.push(`export { ${icon.pascal} } from './icons/${icon.pascal}.js';`);
|
|
166
|
+
dtsExports.push(`export { ${icon.pascal} } from './icons/${icon.pascal}.js';`);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// ── index.js (ESM barrel in src/) ──────────────────────────────────────────
|
|
170
|
+
const indexJS = `// Auto-generated barrel — do not edit
|
|
171
|
+
export { createIcon } from './createIcon.js';
|
|
172
|
+
|
|
173
|
+
${barrelExports.join('\n')}
|
|
174
|
+
`;
|
|
175
|
+
|
|
176
|
+
fs.writeFileSync(path.join(SRC, 'index.js'), indexJS);
|
|
177
|
+
|
|
178
|
+
// ── index.d.ts (types in src/) ─────────────────────────────────────────────
|
|
179
|
+
const indexDTS = `// Auto-generated — do not edit
|
|
180
|
+
export { createIcon, IconProps, IconWeight, IconComponent } from './createIcon';
|
|
181
|
+
|
|
182
|
+
${dtsExports.join('\n')}
|
|
183
|
+
`;
|
|
184
|
+
|
|
185
|
+
fs.writeFileSync(path.join(SRC, 'index.d.ts'), indexDTS);
|
|
186
|
+
|
|
187
|
+
// ── recreate src/icons/.gitkeep ────────────────────────────────────────────
|
|
188
|
+
fs.writeFileSync(path.join(SRC, 'icons', '.gitkeep'), '# Keep directory in Git\n');
|
|
189
|
+
|
|
190
|
+
// ── clean & prepare dist ───────────────────────────────────────────────────
|
|
191
|
+
console.log('Preparing production build in dist/ …');
|
|
192
|
+
fs.rmSync(DIST, { recursive: true, force: true });
|
|
193
|
+
fs.mkdirSync(path.join(DIST, 'icons'), { recursive: true });
|
|
194
|
+
|
|
195
|
+
// ── copy src files to dist ─────────────────────────────────────────────────
|
|
196
|
+
fs.copyFileSync(path.join(SRC, 'createIcon.js'), path.join(DIST, 'createIcon.js'));
|
|
197
|
+
fs.copyFileSync(path.join(SRC, 'createIcon.d.ts'), path.join(DIST, 'createIcon.d.ts'));
|
|
198
|
+
fs.copyFileSync(path.join(SRC, 'index.js'), path.join(DIST, 'index.js'));
|
|
199
|
+
fs.copyFileSync(path.join(SRC, 'index.d.ts'), path.join(DIST, 'index.d.ts'));
|
|
200
|
+
|
|
201
|
+
for (const icon of icons) {
|
|
202
|
+
fs.copyFileSync(path.join(SRC, 'icons', `${icon.pascal}.js`), path.join(DIST, 'icons', `${icon.pascal}.js`));
|
|
203
|
+
fs.copyFileSync(path.join(SRC, 'icons', `${icon.pascal}.d.ts`), path.join(DIST, 'icons', `${icon.pascal}.d.ts`));
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// ── package.json ───────────────────────────────────────────────────────────
|
|
207
|
+
const srcPkg = JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'package.json'), 'utf-8'));
|
|
208
|
+
const pkg = {
|
|
209
|
+
name: srcPkg.name,
|
|
210
|
+
version: srcPkg.version,
|
|
211
|
+
type: 'module',
|
|
212
|
+
description:
|
|
213
|
+
`React Native icon components for ${icons.length}+ icons in 2 weights (Outline & Filled). Tree-shakeable, TypeScript-ready.`,
|
|
214
|
+
main: './index.js',
|
|
215
|
+
module: './index.js',
|
|
216
|
+
types: './index.d.ts',
|
|
217
|
+
exports: {
|
|
218
|
+
'.': {
|
|
219
|
+
import: './index.js',
|
|
220
|
+
types: './index.d.ts',
|
|
221
|
+
},
|
|
222
|
+
'./icons/*': {
|
|
223
|
+
import: './icons/*.js',
|
|
224
|
+
types: './icons/*.d.ts',
|
|
225
|
+
},
|
|
226
|
+
'./createIcon': {
|
|
227
|
+
import: './createIcon.js',
|
|
228
|
+
types: './createIcon.d.ts',
|
|
229
|
+
},
|
|
230
|
+
},
|
|
231
|
+
sideEffects: false,
|
|
232
|
+
files: ['index.js', 'index.d.ts', 'createIcon.js', 'createIcon.d.ts', 'icons/', 'README.md'],
|
|
233
|
+
peerDependencies: {
|
|
234
|
+
react: '>=16.8.0',
|
|
235
|
+
'react-native': '>=0.64.0',
|
|
236
|
+
'react-native-svg': '>=12.0.0',
|
|
237
|
+
},
|
|
238
|
+
keywords: [
|
|
239
|
+
'icons',
|
|
240
|
+
'react-native',
|
|
241
|
+
'react-native-icons',
|
|
242
|
+
'svg-icons',
|
|
243
|
+
'icon-library',
|
|
244
|
+
'reicon',
|
|
245
|
+
'outline',
|
|
246
|
+
'filled',
|
|
247
|
+
'tree-shakeable',
|
|
248
|
+
'typescript',
|
|
249
|
+
'mobile',
|
|
250
|
+
'ios',
|
|
251
|
+
'android',
|
|
252
|
+
],
|
|
253
|
+
author: {
|
|
254
|
+
name: 'devchauhan',
|
|
255
|
+
email: 'dev@devchauhan.in',
|
|
256
|
+
url: 'https://devchauhan.in',
|
|
257
|
+
},
|
|
258
|
+
license: 'MIT',
|
|
259
|
+
repository: { type: 'git', url: 'https://github.com/vezham/reicon', directory: 'packages/icons-react-native' },
|
|
260
|
+
bugs: { url: 'https://github.com/vezham/reicon/issues' },
|
|
261
|
+
homepage: 'https://vezham.com',
|
|
262
|
+
};
|
|
263
|
+
|
|
264
|
+
fs.writeFileSync(path.join(DIST, 'package.json'), JSON.stringify(pkg, null, 2) + '\n');
|
|
265
|
+
|
|
266
|
+
// ── README.md ──────────────────────────────────────────────────────────────
|
|
267
|
+
const readme = `<p align="center">
|
|
268
|
+
<a href="https://npmjs.com/package/reicon-react-native"><img src="https://img.shields.io/npm/v/reicon-react-native?color=black&label=npm" alt="npm version" /></a>
|
|
269
|
+
<a href="https://npmjs.com/package/reicon-react-native"><img src="https://img.shields.io/npm/dm/reicon-react-native?color=black&label=downloads" alt="npm downloads" /></a>
|
|
270
|
+
<a href="https://github.com/dqev/reicon/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MIT-black" alt="MIT License" /></a>
|
|
271
|
+
<a href="https://reicon.dev"><img src="https://img.shields.io/badge/docs-reicon.dev-black" alt="Documentation" /></a>
|
|
272
|
+
</p>
|
|
273
|
+
|
|
274
|
+
# Reicon React Native
|
|
275
|
+
|
|
276
|
+
> ${icons.length}+ pixel-perfect SVG icons • Outline & Filled weights • React Native component wrapper • Zero dependencies • MIT Licensed
|
|
277
|
+
|
|
278
|
+
**Reicon React Native** is the official React Native package for Reicon — a free, open-source SVG icon library with ${icons.length}+ handcrafted, grid-aligned icons built for developers and designers. Every component is optimized for tree-shaking and fully TypeScript-ready.
|
|
279
|
+
|
|
280
|
+
- 🔗 **Website & icon browser:** [reicon.dev](https://reicon.dev)
|
|
281
|
+
- 📦 **Core package:** [reicon](https://npmjs.com/package/reicon)
|
|
282
|
+
- ⚛️ **React package:** [reicon-react](https://npmjs.com/package/reicon-react)
|
|
283
|
+
- 🎨 **Figma plugin:** [reicon.dev/figma](https://reicon.dev/figma)
|
|
284
|
+
|
|
285
|
+
---
|
|
286
|
+
|
|
287
|
+
## Install
|
|
288
|
+
|
|
289
|
+
\`\`\`bash
|
|
290
|
+
npm i reicon-react-native react-native-svg
|
|
291
|
+
# or
|
|
292
|
+
yarn add reicon-react-native react-native-svg
|
|
293
|
+
# or
|
|
294
|
+
bun add reicon-react-native react-native-svg
|
|
295
|
+
\`\`\`
|
|
296
|
+
|
|
297
|
+
**Note:** This package requires \`react-native-svg\` as a peer dependency. Make sure to install it and follow its [setup instructions](https://github.com/software-mansion/react-native-svg#installation).
|
|
298
|
+
|
|
299
|
+
---
|
|
300
|
+
|
|
301
|
+
## Usage
|
|
302
|
+
|
|
303
|
+
\`\`\`jsx
|
|
304
|
+
import { Home, ShieldCheck, AltArrowDown } from 'reicon-react-native';
|
|
305
|
+
|
|
306
|
+
function App() {
|
|
307
|
+
return (
|
|
308
|
+
<View>
|
|
309
|
+
<Home />
|
|
310
|
+
<ShieldCheck size={32} color="#d97757" />
|
|
311
|
+
<AltArrowDown weight="Filled" />
|
|
312
|
+
</View>
|
|
313
|
+
);
|
|
314
|
+
}
|
|
315
|
+
\`\`\`
|
|
316
|
+
|
|
317
|
+
### Props
|
|
318
|
+
|
|
319
|
+
| Prop | Type | Default | Description |
|
|
320
|
+
|------|------|---------|-------------|
|
|
321
|
+
| \`size\` | \`number\` | \`24\` | Icon size in pixels |
|
|
322
|
+
| \`color\` | \`string\` | \`#000000\` | Primary icon color |
|
|
323
|
+
| \`secondaryColor\` | \`string\` | same as color | Secondary color |
|
|
324
|
+
| \`weight\` | \`IconWeight\` | \`Outline\` | Icon weight / style |
|
|
325
|
+
| \`strokeWidth\` | \`number | string\` | — | Override stroke width |
|
|
326
|
+
|
|
327
|
+
Plus all standard \`react-native-svg\` SVG props.
|
|
328
|
+
|
|
329
|
+
### Weights
|
|
330
|
+
|
|
331
|
+
- **Outline** — clean outlined style (default)
|
|
332
|
+
- **Filled** — solid filled style
|
|
333
|
+
|
|
334
|
+
\`\`\`jsx
|
|
335
|
+
import { Home } from 'reicon-react-native';
|
|
336
|
+
|
|
337
|
+
<Home /> {/* Outline (default) */}
|
|
338
|
+
<Home weight="Filled" /> {/* Filled */}
|
|
339
|
+
<Home weight="Filled" color="red" />
|
|
340
|
+
\`\`\`
|
|
341
|
+
|
|
342
|
+
### Direct icon import (smallest bundle)
|
|
343
|
+
|
|
344
|
+
\`\`\`jsx
|
|
345
|
+
import Home from 'reicon-react-native/icons/Home';
|
|
346
|
+
\`\`\`
|
|
347
|
+
|
|
348
|
+
### All react-native-svg props are supported
|
|
349
|
+
|
|
350
|
+
\`\`\`jsx
|
|
351
|
+
<Home
|
|
352
|
+
size={48}
|
|
353
|
+
color="red"
|
|
354
|
+
style={{ marginRight: 8 }}
|
|
355
|
+
onPress={() => console.log('pressed')}
|
|
356
|
+
/>
|
|
357
|
+
\`\`\`
|
|
358
|
+
|
|
359
|
+
---
|
|
360
|
+
|
|
361
|
+
## Tree-shaking — import only what you use
|
|
362
|
+
|
|
363
|
+
Every icon is a standalone ES module. Metro bundler will tree-shake unused icons automatically.
|
|
364
|
+
|
|
365
|
+
\`\`\`jsx
|
|
366
|
+
// ✅ Only Home is included in your bundle
|
|
367
|
+
import { Home } from 'reicon-react-native';
|
|
368
|
+
\`\`\`
|
|
369
|
+
|
|
370
|
+
---
|
|
371
|
+
|
|
372
|
+
## Icon Names
|
|
373
|
+
|
|
374
|
+
Icons use **PascalCase**, derived from their original kebab-case names:
|
|
375
|
+
|
|
376
|
+
| Original name | Import |
|
|
377
|
+
|---------------|--------|
|
|
378
|
+
| \`home\` | \`Home\` |
|
|
379
|
+
| \`shield-check\` | \`ShieldCheck\` |
|
|
380
|
+
| \`alt-arrow-down\` | \`AltArrowDown\` |
|
|
381
|
+
| \`shopping-cart\` | \`ShoppingCart\` |
|
|
382
|
+
| \`user-circle\` | \`UserCircle\` |
|
|
383
|
+
|
|
384
|
+
Browse all ${icons.length}+ icons at [reicon.dev](https://reicon.dev).
|
|
385
|
+
|
|
386
|
+
---
|
|
387
|
+
|
|
388
|
+
## TypeScript
|
|
389
|
+
|
|
390
|
+
Full TypeScript support out of the box:
|
|
391
|
+
|
|
392
|
+
\`\`\`tsx
|
|
393
|
+
import { Home, IconProps, IconWeight } from 'reicon-react-native';
|
|
394
|
+
|
|
395
|
+
const weight: IconWeight = 'Filled';
|
|
396
|
+
const props: IconProps = { size: 32, color: '#d97757', weight };
|
|
397
|
+
|
|
398
|
+
<Home {...props} />
|
|
399
|
+
\`\`\`
|
|
400
|
+
|
|
401
|
+
---
|
|
402
|
+
|
|
403
|
+
## Why Reicon?
|
|
404
|
+
|
|
405
|
+
| | Reicon | React Native Vector Icons | Lucide RN |
|
|
406
|
+
|--|--------|---------------------------|-----------|
|
|
407
|
+
| **Icons** | ${icons.length}+ | 3000+ | 1600+ |
|
|
408
|
+
| **Weights** | Outline + Filled | Varies by set | Outline only |
|
|
409
|
+
| **Tree-shakeable** | ✅ | ❌ | ✅ |
|
|
410
|
+
| **TypeScript** | ✅ | ✅ | ✅ |
|
|
411
|
+
| **Zero dependencies** | ✅ (+ react-native-svg) | ✅ | ✅ (+ react-native-svg) |
|
|
412
|
+
| **MIT License** | ✅ | ✅ | ✅ |
|
|
413
|
+
|
|
414
|
+
---
|
|
415
|
+
|
|
416
|
+
## Related packages
|
|
417
|
+
|
|
418
|
+
| Package | Description |
|
|
419
|
+
|---------|-------------|
|
|
420
|
+
| [\`reicon\`](https://npmjs.com/package/reicon) | Core vanilla JS + CDN |
|
|
421
|
+
| [\`reicon-react\`](https://npmjs.com/package/reicon-react) | React components for all ${icons.length}+ icons |
|
|
422
|
+
| [\`reicon-react-native\`](https://npmjs.com/package/reicon-react-native) | **This package.** React Native components for all ${icons.length}+ icons |
|
|
423
|
+
| [\`reicon-vue\`](https://npmjs.com/package/reicon-vue) | Vue 3 components for all ${icons.length}+ icons |
|
|
424
|
+
| [\`reicon-svelte\`](https://npmjs.com/package/reicon-svelte) | Svelte components for all ${icons.length}+ icons |
|
|
425
|
+
|
|
426
|
+
---
|
|
427
|
+
|
|
428
|
+
## Links
|
|
429
|
+
|
|
430
|
+
- 🌐 Website: [reicon.dev](https://reicon.dev)
|
|
431
|
+
- 📖 Documentation: [reicon.dev/docs](https://reicon.dev/docs)
|
|
432
|
+
- 📦 npm (React Native): [npmjs.com/package/reicon-react-native](https://npmjs.com/package/reicon-react-native)
|
|
433
|
+
- 🐙 GitHub: [github.com/dqev/reicon](https://github.com/dqev/reicon)
|
|
434
|
+
- 🐛 Issues: [github.com/dqev/reicon/issues](https://github.com/dqev/reicon/issues)
|
|
435
|
+
|
|
436
|
+
---
|
|
437
|
+
|
|
438
|
+
## License
|
|
439
|
+
|
|
440
|
+
MIT © [Dev Chauhan](https://devchauhan.in)
|
|
441
|
+
|
|
442
|
+
Free to use in personal and commercial projects.
|
|
443
|
+
`;
|
|
444
|
+
|
|
445
|
+
fs.writeFileSync(path.join(DIST, 'README.md'), readme);
|
|
446
|
+
fs.writeFileSync(path.join(__dirname, '..', 'README.md'), readme);
|
|
447
|
+
|
|
448
|
+
// ── icon name map (for documentation / search) ────────────────────────────
|
|
449
|
+
const nameMap = {};
|
|
450
|
+
for (const icon of icons) {
|
|
451
|
+
nameMap[icon.kebab] = icon.pascal;
|
|
452
|
+
}
|
|
453
|
+
fs.writeFileSync(path.join(DIST, 'icon-names.json'), JSON.stringify(nameMap, null, 2));
|
|
454
|
+
|
|
455
|
+
// ── summary ────────────────────────────────────────────────────────────────
|
|
456
|
+
const totalFiles = (icons.length * 2) + 5;
|
|
457
|
+
console.log(`\nDone!`);
|
|
458
|
+
console.log(` Icons: ${icons.length}`);
|
|
459
|
+
console.log(` Weights: Outline + Filled`);
|
|
460
|
+
console.log(` Files: ${totalFiles}`);
|
|
461
|
+
console.log(` Output: ${DIST}`);
|
|
462
|
+
console.log(`\nTo publish:`);
|
|
463
|
+
console.log(` cd ${DIST} && npm publish --access public`);
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { ForwardRefExoticComponent, RefAttributes } from 'react';
|
|
2
|
+
import { SvgProps } from 'react-native-svg';
|
|
3
|
+
|
|
4
|
+
export type IconWeight = 'Filled' | 'Outline';
|
|
5
|
+
|
|
6
|
+
export interface IconProps extends Omit<SvgProps, 'color'> {
|
|
7
|
+
/** Primary color. Default: `currentColor` (black in RN) */
|
|
8
|
+
color?: string;
|
|
9
|
+
/** Secondary color. Default: same as color */
|
|
10
|
+
secondaryColor?: string;
|
|
11
|
+
/** Icon size (number for RN). Default: `24` */
|
|
12
|
+
size?: number;
|
|
13
|
+
/** Icon weight / style. Default: `Outline` */
|
|
14
|
+
weight?: IconWeight;
|
|
15
|
+
/** Override stroke-width on stroked weights */
|
|
16
|
+
strokeWidth?: number | string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export type IconComponent = ForwardRefExoticComponent<IconProps & RefAttributes<any>>;
|
|
20
|
+
|
|
21
|
+
export declare function createIcon(
|
|
22
|
+
displayName: string,
|
|
23
|
+
iconData: Partial<Record<string, string>>,
|
|
24
|
+
): IconComponent;
|
|
25
|
+
|
|
26
|
+
export default createIcon;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { forwardRef, createElement } from 'react';
|
|
2
|
+
import { SvgXml } from 'react-native-svg';
|
|
3
|
+
|
|
4
|
+
const W_MAP = { Filled: 'F', Outline: 'O' };
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Factory that builds a forwardRef icon component for React Native.
|
|
8
|
+
* @param {string} displayName PascalCase icon name
|
|
9
|
+
* @param {Object} iconData { F?: string, O?: string }
|
|
10
|
+
*/
|
|
11
|
+
const createIcon = (displayName, iconData) => {
|
|
12
|
+
const Icon = forwardRef(
|
|
13
|
+
/**
|
|
14
|
+
* @param {import('./createIcon').IconProps} props
|
|
15
|
+
* @param {import('react').Ref<Svg>} ref
|
|
16
|
+
*/
|
|
17
|
+
(
|
|
18
|
+
{
|
|
19
|
+
color,
|
|
20
|
+
secondaryColor,
|
|
21
|
+
size = 24,
|
|
22
|
+
weight = 'Outline',
|
|
23
|
+
strokeWidth,
|
|
24
|
+
style,
|
|
25
|
+
...rest
|
|
26
|
+
},
|
|
27
|
+
ref,
|
|
28
|
+
) => {
|
|
29
|
+
const key = W_MAP[weight] || 'O';
|
|
30
|
+
let html = iconData[key] || iconData[Object.keys(iconData)[0]] || '';
|
|
31
|
+
|
|
32
|
+
if (strokeWidth != null) {
|
|
33
|
+
html = html.replace(/stroke-width="[^"]*"/g, `stroke-width="${strokeWidth}"`);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (color != null) {
|
|
37
|
+
html = html.replace(/currentColor/g, color);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Replace secondary color placeholder if present
|
|
41
|
+
if (secondaryColor) {
|
|
42
|
+
html = html.replace(/__RI_SECONDARY__/g, secondaryColor);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const svgMarkup = `<svg xmlns="http://www.w3.org/2000/svg" width="${size}" height="${size}" viewBox="0 0 24 24" fill="none">${html}</svg>`;
|
|
46
|
+
|
|
47
|
+
return createElement(SvgXml, {
|
|
48
|
+
ref,
|
|
49
|
+
xml: svgMarkup,
|
|
50
|
+
width: size,
|
|
51
|
+
height: size,
|
|
52
|
+
style,
|
|
53
|
+
...rest,
|
|
54
|
+
});
|
|
55
|
+
},
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
Icon.displayName = displayName;
|
|
59
|
+
return Icon;
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
export { createIcon };
|
|
63
|
+
export default createIcon;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Keep directory in Git
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2020",
|
|
4
|
+
"module": "ESNext",
|
|
5
|
+
"lib": ["ES2020"],
|
|
6
|
+
"jsx": "react-native",
|
|
7
|
+
"declaration": true,
|
|
8
|
+
"outDir": "./dist",
|
|
9
|
+
"rootDir": "./src",
|
|
10
|
+
"strict": true,
|
|
11
|
+
"esModuleInterop": true,
|
|
12
|
+
"skipLibCheck": true,
|
|
13
|
+
"forceConsistentCasingInFileNames": true,
|
|
14
|
+
"moduleResolution": "node",
|
|
15
|
+
"resolveJsonModule": true,
|
|
16
|
+
"allowSyntheticDefaultImports": true
|
|
17
|
+
},
|
|
18
|
+
"include": ["src/**/*"],
|
|
19
|
+
"exclude": ["node_modules", "dist"]
|
|
20
|
+
}
|